import React, { Fragment } from "react";
import classNames from "classnames";
import { findDOMNode } from "react-dom";
import Checkbox, { CheckboxChangeEvent } from "@zcy/doraemon/lib/checkbox";

export interface CascaderOptionType {
  parent?: CascaderOptionType,
  value: string;
  label: React.ReactNode;
  level: number;
  disabled?: boolean;
  children?: Array<CascaderOptionType>;
  __IS_FILTERED_OPTION?: boolean;
  indeterminate?: boolean;
  checked?: boolean;
  defaultValue?: string[];
}

export interface MenusProps {
  value?: CascaderOptionType[];
  clearSelection: (e?: any) => void;
  activeValue?: CascaderOptionType[];
  options: CascaderOptionType[];
  prefixCls?: string;
  expandTrigger?: string;
  onSelect: (
    targetOption: CascaderOptionType,
    menuIndex: number,
    e: any
  ) => void;
  onCheck?: (targetOption: CascaderOptionType, e: any) => void | undefined;
  visible?: boolean;
}

export interface MenusState {
  activeLevel: number;
}

class Menus extends React.Component<MenusProps, MenusState> {
  static defaultProps = {
    options: [],
    value: [],
    activeValue: [],
    onSelect() {},
    onCheck() {},
    prefixCls: "rc-cascader-menus",
    visible: false,
    expandTrigger: "click"
  };

  private menuItems: any;
  private delayTimer: any;

  constructor(props: MenusProps) {
    super(props);
    this.menuItems = {};
    
    // 根据第一个选中的值的level初始化默认选中level
    this.state = {
      activeLevel: (props.value && props.value.length) ? props.value[props.value.length -1].level! : 1,
    };
  }

  componentDidMount() {
    this.scrollActiveItemToView();
  }

  componentDidUpdate(prevProps: MenusProps) {
    if (!prevProps.visible && this.props.visible) {
      this.scrollActiveItemToView();
    }
  }

  getOption(option: CascaderOptionType, menuIndex: number) {
    const { prefixCls, expandTrigger } = this.props;
    let { onSelect, onCheck } = this.props;
    const { activeLevel } = this.state;
    let expandProps: any = {};
    let menuItemCls = `${prefixCls}-menu-item`;
    const hasChildren = option.children && option.children.length > 0;
    if ( (hasChildren && option.level < activeLevel)) {
      menuItemCls += ` ${prefixCls}-menu-item-expand`;
    }
    if (expandTrigger === "hover" && hasChildren && activeLevel > option.level) {
      expandProps = {
        onMouseEnter: this.delayOnSelect.bind(this, onSelect as any),
        onMouseLeave: this.delayOnSelect.bind(this),
        onClick: onSelect
      };
    }
    if (this.isActiveOption(option, menuIndex)) {
      menuItemCls += ` ${prefixCls}-menu-item-active`;
      expandProps.ref = this.saveMenuItem(menuIndex);
    }
    if (option.disabled) {
      menuItemCls += ` ${prefixCls}-menu-item-disabled`;
    }
    let title = "";
    if (typeof option.label === "string") {
      title = option.label;
    }

    let handleCheck = (e: CheckboxChangeEvent) => {
      if (onCheck) {
        onCheck(option, e);
      }
    };

    let handleSelect = (e: React.MouseEvent<HTMLInputElement>) => {
      if (onSelect && activeLevel > option.level) {
        onSelect(option, menuIndex, e);
      }
    };
    return (
      <li
        key={option.value}
        className={menuItemCls}
        title={title}
        {...expandProps}
        onClick={handleSelect}
      >
        {activeLevel === option.level && (
          <Checkbox
            onChange={handleCheck}
            disabled={option.disabled}
            indeterminate={option.indeterminate}
            checked={option.checked}
          />
        )}
        <span>{option.label}</span>
      </li>
    );
  }
  // TODO:
  getActiveOptions(values?: any[]) {
    const activeValue = this.props.activeValue;
    return (activeValue && activeValue.length) ? activeValue : [];
  }

  // TODO:
  getShowOptions() {
    const { options } = this.props;
    const { activeLevel } = this.state;
    const result = this.getActiveOptions()
      .filter((activeOption) => !!activeOption.children)
      .map((activeOption: CascaderOptionType) => activeOption.children!)
    result.unshift(options);
    return result.slice(0, Number(activeLevel));
  }

  // 生成省市区option
  genLevelOptions() {
    const { prefixCls } = this.props;
    const { activeLevel } = this.state;
    const menuItemCls1 = classNames({
      [`${prefixCls}-menu-item`]: true,
      [`${prefixCls}-menu-item-active`]: activeLevel === 1
    });
    const menuItemCls2 = classNames({
      [`${prefixCls}-menu-item`]: true,
      [`${prefixCls}-menu-item-active`]: activeLevel === 2
    });
    const menuItemCls3 = classNames({
      [`${prefixCls}-menu-item`]: true,
      [`${prefixCls}-menu-item-active`]: activeLevel === 3
    });

    return (
      <ul className={`${prefixCls}-menu`}>
        <li
          className={menuItemCls1}
          onClick={() => this.handleLevelSelect(1)}
          style={{ textAlign: "center" }}
        >
          <span>省</span>
        </li>
        <li
          className={menuItemCls2}
          onClick={() => this.handleLevelSelect(2)}
          style={{ textAlign: "center" }}
        >
          <span>市</span>
        </li>
        <li
          className={menuItemCls3}
          onClick={() => this.handleLevelSelect(3)}
          style={{ textAlign: "center" }}
        >
          <span>区</span>
        </li>
      </ul>
    );
  }

  // 区划级别选择
  handleLevelSelect = (value: number) => {
    const { clearSelection } = this.props;
    this.setState({
      activeLevel: value,
    })
    clearSelection();
  }

  delayOnSelect(onSelect: (args: any[]) => void, ...args: any[]) {
    if (this.delayTimer) {
      clearTimeout(this.delayTimer);
      this.delayTimer = null;
    }
    if (typeof onSelect === "function") {
      this.delayTimer = setTimeout(() => {
        onSelect(args);
        this.delayTimer = null;
      }, 150);
    }
  }

  scrollActiveItemToView() {
    // scroll into view
    const optionsLength = this.getShowOptions().length;
    for (let i = 0; i < optionsLength; i++) {
      const itemComponent = this.menuItems[i];
      if (itemComponent) {
        const target = findDOMNode(itemComponent) as HTMLElement;
        // target.parentNode.scrollTop = target.offsetTop;
        if (target.parentElement) {
          target.parentElement.scrollTop = target.clientTop;
        }
      }
    }
  }

  isActiveOption(option: CascaderOptionType, menuIndex: number) {
    const { activeValue = [] } = this.props;
    return activeValue[menuIndex] === option;
  }

  saveMenuItem = (index: number) => (node: any) => {
    this.menuItems[index] = node;
  };

  render() {
    const { prefixCls } = this.props;
    let createOptions = () => {
      let showOptions = this.getShowOptions();
      return (
        <Fragment>
          {this.genLevelOptions()}
          {showOptions.map(
            (options: CascaderOptionType[], menuIndex: number) => (
              <ul
                className={`${prefixCls}-menu`}
                key={menuIndex}
              >
                {options.map((option: CascaderOptionType) =>
                  this.getOption(option, menuIndex)
                )}
              </ul>
            )
          )}
        </Fragment>
      );
    };
    return <div>{createOptions()}</div>;
  }
}

export default Menus;
